package chartUtils;

import java.util.ArrayList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import mymath.Functions;

public class ChartSupport {

    private ChartSupport() {
    }

    public static LineChart<Number, Number> addSeriesToXYChart(PointList pl, String functionName, LineChart<Number, Number> lineChart) {
        boolean isFunctionPlotable = !Functions.hasPointListUndefinedValues(pl);
        if (isFunctionPlotable) {
            XYChart.Series series = ChartSupport.getXYChartSeriesForPoints(pl.getPoints());
            series.setName(functionName);
            lineChart.getData().add(series);

        } else {
            System.out.println("func01 cannot be plotted!");
        }
        System.out.println("X: " + pl.getXmin() + ".." + pl.getXmax()
                + "\nY: " + pl.getYmin() + " .." + pl.getYmax());
        return lineChart;
    }

    public static XYChart.Series getXYChartSeriesForPoints(ArrayList<Point> points) {
        //populating the series with data   
        XYChart.Series series = new XYChart.Series();
        points.stream().forEach((point) -> {
            series.getData().add(new XYChart.Data(point.getX(), point.getY()));
        });

        return series;
    }

    public static VBox createVBoxLayoutForChart(LineChart<Number, Number> lineChart) {
        VBox layout = new VBox(10);
        layout.setPadding(new Insets(10));
        layout.setAlignment(Pos.CENTER);
        layout.getChildren().add(lineChart);
        return layout;
    }

    public static VBox addCursorCoords(VBox layout, Label cursorCoords) {
        layout.getChildren().add(0, cursorCoords);
        return layout;
    }

    public static Label createCursorGraphCoordsMonitorLabel(LineChart<Number, Number> lineChart) {
        final Axis<Number> xAxis = lineChart.getXAxis();
        final Axis<Number> yAxis = lineChart.getYAxis();

        final Label cursorCoords = new Label();

        final Node chartBackground = lineChart.lookup(".chart-plot-background");
        chartBackground.getParent().getChildrenUnmodifiable().stream().filter((n) -> (n != chartBackground && n != xAxis && n != yAxis)).forEach((n) -> {
            n.setMouseTransparent(true);
        });
        chartBackground.setOnMouseEntered((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(true);
        });

        chartBackground.setOnMouseMoved((MouseEvent mouseEvent) -> {
            cursorCoords.setText(
                    String.format(
                            "(%.2f | %.2f)",
                            xAxis.getValueForDisplay(mouseEvent.getX()),
                            yAxis.getValueForDisplay(mouseEvent.getY())
                    )
            );
        });

        chartBackground.setOnMouseExited((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(false);
        });

        xAxis.setOnMouseEntered((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(true);
        });

        xAxis.setOnMouseMoved((MouseEvent mouseEvent) -> {
            cursorCoords.setText(
                    String.format(
                            "x = %.2f",
                            xAxis.getValueForDisplay(mouseEvent.getX())
                    )
            );
        });

        xAxis.setOnMouseExited((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(false);
        });

        yAxis.setOnMouseEntered((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(true);
        });

        yAxis.setOnMouseMoved((MouseEvent mouseEvent) -> {
            cursorCoords.setText(
                    String.format(
                            "y = %.2f",
                            yAxis.getValueForDisplay(mouseEvent.getY())
                    )
            );
        });

        yAxis.setOnMouseExited((MouseEvent mouseEvent) -> {
            cursorCoords.setVisible(false);
        });

        return cursorCoords;
    }

}
